package com.hjy.attendance.util;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

import java.io.*;
import java.sql.Clob;
import java.sql.SQLException;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @program: springcloud-project
 * @description: 字符串工具类
 * @author: xjr
 * @create: 2020-03-09 22:22
 **/

public class StringUtils extends org.springframework.util.StringUtils {
    public static final String COMMA = ",";
    public static final String CROSSBAR = "-";
    public static final Pattern CAME_2_UNDERLINE_PATTERN = Pattern.compile("[A-Z]([a-z\\d]+)?");
    public static final Pattern UNDERLINE_2_CAMEL_PATTERN = Pattern.compile("([A-Za-z\\d]+)(_)?");

    /**
     * 在第一次出现分隔符之前获取子串,分隔符没有返回
     *
     * 例如:
     * StringUtils.substringBefore(null, *)      = null
     * StringUtils.substringBefore("", *)        = ""
     * StringUtils.substringBefore("abc", "a")   = ""
     * StringUtils.substringBefore("abcba", "b") = "a"
     * StringUtils.substringBefore("abc", "c")   = "ab"
     * StringUtils.substringBefore("abc", "d")   = "abc"
     * StringUtils.substringBefore("abc", "")    = ""
     * StringUtils.substringBefore("abc", null)  = "abc"
     *
     * @param str       原始字符串
     * @param separator 要查找的字符串
     * @return 在第一次出现分离器之前的子串
     */
    public static String substringBefore(String str, String separator) {
        if (isEmpty(str) || separator == null) {
            return str;
        }
        if (separator.length() == 0) {
            return "";
        }
        int pos = str.indexOf(separator);
        if (pos == -1) {
            return str;
        }
        return str.substring(0, pos);
    }

    /**
     * 首字母转小写
     *
     * @param str 要转换的字符串
     * @return
     */
    public static String toLowerCaseFirstChar(String str) {
        if (isEmpty(str) || Character.isLowerCase(str.charAt(0))) {
            return str;
        } else {
            return Character.toLowerCase(str.charAt(0)) + str.substring(1);
        }
    }


    /**
     * 首字母转大写
     *
     * @param str 要转换的字符串
     * @return
     */
    public static String toUpperCaseFirstChar(String str) {
        if (isEmpty(str) || Character.isLowerCase(str.charAt(0))) {
            return str;
        } else {
            return Character.toUpperCase(str.charAt(0)) + str.substring(1);
        }
    }

    /**
     * 根据分隔符把string 转为 list 对象
     *
     * @param rawStr 原始字符串
     * @param separator 分隔符
     * @return
     */
    public static List<String> delimitedStringToList(String rawStr, String separator) {
        if (isEmpty(rawStr)) {
            return Collections.emptyList();
        }
        return Arrays.asList(rawStr.split(separator));
    }

    /**
     * 将字符串通过分隔符','分隔为集合
     *
     * @param rawStr
     * @return
     */
    public static List<String> commaDelimitedStringToList(String rawStr) {
        return delimitedStringToList(rawStr, COMMA);
    }

    public static String of(Object obj) {
        if (obj == null) {
            return "";
        }
        return String.valueOf(obj);
    }

    /**
     * 根据文件地址读入字符串
     *
     * @param fileName 文件路径
     * @return
     */
    public static String readFromFile(String fileName) {
        try (FileReader fr = new FileReader(fileName);
             BufferedReader br = new BufferedReader(fr)
        ) {
            String line;
            StringBuilder sb = new StringBuilder();
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 根据文件读入字符串
     * @param file 文件
     * @return
     */
    public static String readFromFile(File file) {
        return readFromFile(file.getAbsolutePath());
    }

    /**
     * 包含格式换行符等
     * @param fileName 文件名
     * @return
     */
    public static String readFromFileRaw(String fileName) {
        String encoding = "UTF-8";
        File file = new File(fileName);
        long filelength = file.length();
        byte[] filecontent = new byte[(int) filelength];
        try {
            FileInputStream in = new FileInputStream(file);
            in.read(filecontent);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            return new String(filecontent, encoding);
        } catch (UnsupportedEncodingException e) {
            System.err.println("The OS does not support " + encoding);
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 将Map转换为Http参数格式
     * @param paramMap map参数
     * @return
     */
    public static String toParamString(Map<String, String> paramMap) {
        if (paramMap == null || paramMap.size() == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        int size = paramMap.size();
        int index = 0;
        for (String key : paramMap.keySet()) {
            String value = paramMap.get(key);
            sb.append(key);
            sb.append("=");
            sb.append(value);
            if (++index != size) {
                sb.append("&");
            }
        }
        return sb.toString();
    }

    /**
     * 根据字符串创建文件
     * @param str 字符串
     * @param fileName 文件名
     * @throws IOException
     */
    public static void writeToFile(String str, String fileName) throws IOException {
        File file = new File(fileName);
        if (!file.exists()) {
            boolean mkdirs = file.getParentFile().mkdirs();
            if (mkdirs && !file.createNewFile()) {
                throw new IOException("创建文件失败");
            }
        }
        try (FileOutputStream fos = new FileOutputStream(fileName)) {
            fos.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 是否不为空
     * @param str 字符串
     * @return
     */
    public static boolean isNotEmpty(Object str) {
        return !isEmpty(str);
    }

    /**
     * 下划线转驼峰法(默认小驼峰)
     *
     * @param line
     *            源字符串
     * @param smallCamel
     *            大小驼峰,是否为小驼峰(驼峰，第一个字符是大写还是小写)
     * @return 转换后的字符串
     */
    public static String underline2Camel(String line, boolean... smallCamel) {
        if (isEmpty(line)) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        Matcher matcher = UNDERLINE_2_CAMEL_PATTERN.matcher(line);
        //匹配正则表达式
        while (matcher.find()) {
            String word = matcher.group();
            //当是true 或则是空的情况
            if ((smallCamel.length == 0 || smallCamel[0]) && matcher.start() == 0) {
                sb.append(Character.toLowerCase(word.charAt(0)));
            } else {
                sb.append(Character.toUpperCase(word.charAt(0)));
            }

            int index = word.lastIndexOf('_');
            if (index > 0) {
                sb.append(word.substring(1, index).toLowerCase());
            } else {
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰法转下划线
     *
     * @param line
     *            源字符串
     * @return 转换后的字符串
     */
    public static String camel2Underline(String line) {
        if (isEmpty(line)) {
            return "";
        }
        line = String.valueOf(line.charAt(0)).toUpperCase()
                .concat(line.substring(1));
        StringBuilder sb = new StringBuilder();
        Matcher matcher = CAME_2_UNDERLINE_PATTERN.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(word.toUpperCase());
            sb.append(matcher.end() == line.length() ? "" : "_");
        }
        return sb.toString();
    }


    /**
     * 根据指定的字段将集合中的元素用逗号拼接成字符串
     * @param collection 集合
     * @param mapper 字段匹配
     * @param <T> 实体类型
     * @return 以逗号分隔的字符串
     */
    public static <T> String collectionToCommaDelimitedString(Collection<T> collection,
                                                              Function<? super T, String> mapper) {
        if (CollectionUtils.isEmpty(collection)) {
            return "";
        }
        return collection.stream()
                .map(mapper)
                .reduce((s1, s2) -> s1 + COMMA + s2)
                .orElse("");
    }

    /**
     * XML 转化成 MAP
     *
     * @throws Exception 系统异常
     */
    public static Map<String, Object> xmlConvertMap(String xml) throws Exception {
        Document doc = DocumentHelper.parseText(xml);
        Map<String, Object> result = new HashMap<>();
        Element root = doc.getRootElement().element("msgBody");
        List<Map<String, Object>> listMap = new ArrayList<>();
        for (Iterator iterator = root.elementIterator(); iterator.hasNext(); ) {
            Element e = (Element) iterator.next();
            List list = e.elements();
            if (list.size() > 0) {
                listMap.add(dom2Map(e));
            } else {
                Map<String, Object> map = new HashMap<>();
                map.put(e.getName(), e.getText());
                listMap.add(map);
            }
        }
        for (Map<String, Object> temp : listMap) {
            if (isNotEmpty(temp)) {
                for (String s : temp.keySet()) {
                    result.put(s, temp.get(s));
                }
            }
        }
        return result;
    }

    /**
     * XML 转化成 MAP
     *
     * @throws Exception 系统异常
     */
    public static Map<String, Object> dom2Map(Element e) throws Exception {
        Map<String, Object> map = new HashMap();
        List list = e.elements();
        if (list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                Element iter = (Element) list.get(i);
                List mapList = new ArrayList();
                if (iter.elements().size() > 0) {
                    Map m = dom2Map(iter);
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!"java.util.ArrayList".equals(obj.getClass().getName())) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(m);
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(m);
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), m);
                    }
                } else {
                    if (map.get(iter.getName()) != null) {
                        Object obj = map.get(iter.getName());
                        if (!obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = new ArrayList();
                            mapList.add(obj);
                            mapList.add(iter.getText());
                        }
                        if (obj.getClass().getName().equals("java.util.ArrayList")) {
                            mapList = (List) obj;
                            mapList.add(iter.getText());
                        }
                        map.put(iter.getName(), mapList);
                    } else {
                        map.put(iter.getName(), iter.getText());
                    }
                }
            }
        } else {
            map.put(e.getName(), e.getText());
        }
        return map;
    }

    /**
     *  Clob类型 转String
     * @param clob
     * @return
     * @throws SQLException
     * @throws IOException
     */
    public static String ClobToString(Clob clob) throws SQLException, IOException {
        String reString = "";
        Reader is = clob.getCharacterStream();
        BufferedReader br = new BufferedReader(is);
        String s = br.readLine();
        StringBuffer sb = new StringBuffer();
        while (s != null) {
            sb.append(s);
            s = br.readLine();
        }
        reString = sb.toString();
        if (br != null) {
            br.close();
        }
        if (is != null) {
            is.close();
        }
        return reString;
    }
}
